package phase1.part3;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.logging.Logger;

/**
 * 
 * 
 * @author John Girata
 * @version Nov 1, 2012
 */
public class InputFileReader {
	private static final String STATES = "STATES";
	private static final String START = "START";
	private static final String ACCEPTING = "ACCEPT";

	private static final Logger LOG;

	private Map<String, State> states;
	private State start;
	private List<State> accepting;
	private Map<State, List<Transition>> transitions;

	static {
		LOG = Logger.getLogger("phase1.part3.InputFileReader");
	}

	public InputFileReader(String filename) throws FileNotFoundException,
			FileFormatException {
		states = new HashMap<>();
		accepting = new ArrayList<>();
		transitions = new HashMap<>();

		Scanner scanner = new Scanner(new File(filename));

		while (scanner.hasNext()) {
			String line = scanner.nextLine();

			if (line.isEmpty()) {
				continue;
			}

			if (line.indexOf(STATES) == 0) {
				processStates(line);
			} else if (line.indexOf(START) == 0) {
				processStart(line);
			} else if (line.indexOf(ACCEPTING) == 0) {
				processAccepting(line);
			} else {
				processTransition(line);
			}
		}
	}

	private final void processStates(String line) throws FileFormatException {
		String[] parts = postSpace(line).split(",");

		for (String label : parts) {
			states.put(label, new State(label));
		}

		LOG.info("Got states " + states);
	}

	private final void processStart(String line) throws FileFormatException {
		String label = postSpace(line);
		start = states.get(label);

		LOG.info("Got starting state " + start);
	}

	private final void processAccepting(String line) throws FileFormatException {
		String[] parts = line.split(" ");
		String tokenClass = parts[1];
		String[] stateLabels = parts[2].split(",");

		for (String label : stateLabels) {
			State s = states.get(label);
			s.setAccepting(true);
			s.setTokenClass(tokenClass);
			accepting.add(s);
		}

		LOG.info("Got accepting states " + accepting);
	}

	private final void processTransition(String line) {
		String[] parts = line.split(",");

		String from = parts[0];
		String pattern = parts[1];
		String to = parts[2];

		Matcher matcher = new Matcher(pattern);
		Transition transition = new Transition(states.get(to), matcher);
		states.get(from).addTransition(transition);

		LOG.info("Got transition " + transition);
	}

	private String postSpace(String line) throws FileFormatException {
		int space = line.indexOf(' ');

		if (space == -1) {
			throw new FileFormatException();
		}

		String postSpace = line.substring(space + 1);
		return postSpace;
	}

	public Map<String, State> getStates() {
		return states;
	}

	public State getStart() {
		return start;
	}

	public List<State> getAccepting() {
		return accepting;
	}

	public Map<State, List<Transition>> getTransitions() {
		return transitions;
	}

	public static class FileFormatException extends Exception {
		private static final long serialVersionUID = 8448704966112475242L;

		public FileFormatException() {
		}

		public FileFormatException(String message, Throwable cause,
				boolean enableSuppression, boolean writableStackTrace) {
			super(message, cause, enableSuppression, writableStackTrace);
		}

		public FileFormatException(String message, Throwable cause) {
			super(message, cause);
		}

		public FileFormatException(String message) {
			super(message);
		}

		public FileFormatException(Throwable cause) {
			super(cause);
		}
	}
}
